const MYKEY = Symbol();
class User {
    constructor(key,name,age){
        this[MYKEY] = key;
        this.name = name;
        this.age = age;
    }
    checkKEY(key){
        return this[MYKEY] === key;
    }
}

let user = new User(123, 'Curry', 29);
console.log(user.name, user.age, user[MYKEY]);
console.log(user.checkKEY(123));   //true
console.log(user.checkKEY(456));   //false
console.log(Object.keys(user));    //[ 'name', 'age' ]
console.log(JSON.stringify(user)); //{"name":"Curry","age":29}

//作为属性名
//由于每一个 Symbol 的值都是不相等的，所以 Symbol 作为对象的属性名，可以保证属性不重名
let sy = Symbol("key1");
 
// 写法1
let syObject1 = {};
syObject1[sy] = "kk";
console.log(syObject1);    // {Symbol(key1): "kk"}
 
// 写法2
let syObject2 = {
  [sy]: "kk"
};
console.log(syObject2);    // {Symbol(key1): "kk"}
 
// 写法3
let syObject3 = {};
Object.defineProperty(syObject3, sy, {value: "kk"});
console.log(syObject3);   // {Symbol(key1): "kk"}

//Symbol 作为对象属性名时不能用.运算符，要用方括号。因为.运算符后面是字符串，所以取到的是字符串 sy 属性，而不是 Symbol 值 sy 属性。

let syObject4 = {};
syObject4[sy] = "kk";
 
syObject4[sy];  // "kk"
syObject4.sy;   // undefined

/*ps:
 Symbol 值作为属性名时，该属性是公有属性不是私有属性，可以在类的外部访问。但是不会出现在 for...in 、 for...of 的循环中，
 也不会被 Object.keys() 、 Object.getOwnPropertyNames() 返回。如果要读取到一个对象的 Symbol 属性，
 可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。*/

let syObject5 = {};
syObject5[sy] = "kk";
console.log(syObject5);
 
for (let i in syObject5) {
  console.log(i);
}    // 无输出
 
Object.keys(syObject5);                     // []
Object.getOwnPropertySymbols(syObject5);    // [Symbol(key1)]
Reflect.ownKeys(syObject5);                 // [Symbol(key1)]

//但是使用 Symbol 定义常量，这样就可以保证这一组常量的值都不相等
const COLOR_RED = Symbol("red");
const COLOR_YELLOW = Symbol("yellow");
const COLOR_BLUE = Symbol("blue");
 //Symbol 的值是唯一的，所以不会出现相同值得常量，
function getConstantName(color) {
    switch (color) {
        case COLOR_RED :
            return "COLOR_RED";
        case COLOR_YELLOW :
            return "COLOR_YELLOW ";
        case COLOR_BLUE:
            return "COLOR_BLUE";
        default:
            throw new Exception('Can't find this color');
    }
}
//Symbol.for() 类似单例模式，首先会在全局搜索被登记的 Symbol 中是否有该字符串参数作为名称的 Symbol 值，
//如果有即返回该 Symbol 值，若没有则新建并返回一个以该字符串参数为名称的 Symbol 值，并登记在全局环境中供搜索。

let yellow = Symbol("Yellow");
let yellow1 = Symbol.for("Yellow");
yellow === yellow1;      // false
 
let yellow2 = Symbol.for("Yellow");
yellow1 === yellow2;     // true

//Symbol.keyFor() 返回一个已登记的 Symbol 类型值的 key ，用来检测该字符串参数作为名称的 Symbol 值是否已被登记。

let yellow3 = Symbol.for("Yellow");
Symbol.keyFor(yellow3);    // "Yellow"